package service

import (
	"errors"
	"fmt"
	"gorm.io/gorm"
	"time"
	"todolist/cache"
	"todolist/model"
	"todolist/pkg/e"
	"todolist/pkg/utils"
	"todolist/serializer"
)

type UserService struct {
	Username string `form:"user_name" json:"user_name" binding:"required,min=3,max=15" example:"FanOne"`
	Password string `form:"password" json:"password" binding:"required,min=5,max=16" example:"FanOne5565"`
}

func (service *UserService) Register() *serializer.Response {
	var user model.User
	var count int64
	code := e.SUCCESS

	model.DB.Model(&model.User{}).Where("user_name=?", service.Username).First(&user).Count(&count)

	if count == 1 {
		code := e.ErrorExistUser
		return &serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}

	user.UserName = service.Username
	if err := user.SetPassword(service.Password); err != nil {
		utils.LogrusObj.Info(err)
		code = e.ErrorFailEncryption
		return &serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}

	if err := model.DB.Create(&user).Error; err != nil {
		utils.LogrusObj.Info(err)
		code := e.ErrorDatabase
		return &serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}

	return &serializer.Response{
		Status: code,
		Msg:    e.GetMsg(code),
	}
}

func (service *UserService) Login() serializer.Response {
	var user model.User
	code := e.SUCCESS
	if err := model.DB.Where("user_name=?", service.Username).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			utils.LogrusObj.Info(err)
			code = e.ErrorNotExistUser
			return serializer.Response{
				Status: code,
				Msg:    e.GetMsg(code),
			}
		}
		utils.LogrusObj.Info(err)
		code := e.ErrorDatabase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	if !user.CheckPassword(service.Password) {
		code = e.ErrorNotCompare
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}

	key := fmt.Sprintf("token-%d", user.ID)
	token, err := cache.RedisClient.Get(key).Result()
	if err != nil {
		token, err = utils.GenerateToken(user.ID, service.Username, 0)

		if err != nil {
			utils.LogrusObj.Info(err)
			code = e.ErrorAuthToken
			return serializer.Response{
				Status: code,
				Msg:    e.GetMsg(code),
			}
		}
		cache.RedisClient.Set(key, token, 24*time.Hour)
	}

	return serializer.Response{
		Status: code,
		Data:   serializer.TokenData{User: serializer.BuildUser(user), Token: token},
		Msg:    e.GetMsg(code),
	}
}
